package com.zebra.remoting.tms;

import cn.hutool.core.util.StrUtil;
import com.zebra.common.ZebraException;
import com.zebra.remoting.CommandHandler;
import com.zebra.remoting.config.*;
import com.zebra.remoting.connection.Connection;
import com.zebra.remoting.protocol.PoolType;
import com.zebra.remoting.protocol.ZebraCommand;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import org.springframework.stereotype.Service;

import java.util.concurrent.Executor;

/**
 * TMS 服务器 需要继承这个 handler
 * sk
 */
@Service
public abstract class AbstractServerHandler implements CommandHandler {
    private static final InternalLogger log = InternalLoggerFactory.getInstance(AbstractServerHandler.class);
    private PingMessage pingMessage = new PingMessage();
    @Override
    public void handleCommand(ChannelHandlerContext ctx, Object msg) throws Exception {
        ZebraCommand zebraCommand = (ZebraCommand) msg;
        zebraCommand.setChannel(ctx.channel());
        if (BasisCommandCode.PING.cmd() == zebraCommand.getCmd()) {
            zebraCommand.setLogs(true);
            zebraCommand.sendMessage(pingMessage);
            return;
        }

        if (BasisCommandCode.REGISTER.cmd() == zebraCommand.getCmd()) {
            RegisterConnectMessage connectMessage = (RegisterConnectMessage) zebraCommand.getRequest();
            if (connectMessage.getServerType() == ServerType.Register.value()){
                Connection connection = new Connection(ctx.channel(), ServerType.valueOf(connectMessage.getServerType()), connectMessage.getServerId());
                log.warn("REGISTER Register connection {} ", connection.toString());
                log.warn("REGISTER TMS Register Info {} ", StrUtil.join(", ", TmsConfigInfoManager.getInstance().findRegisterALL()));
            }else if (connectMessage.getServerType() == ServerType.Gateway.value()) {
                Connection connection = new Connection(ctx.channel(), ServerType.valueOf(connectMessage.getServerType()), connectMessage.getServerId());
                TmsConfigInfoManager.getInstance().registerGateway(connection);
                log.warn("REGISTER Gateway connection {} ", TmsConfigInfoManager.getInstance().buildLinkTms());
            }
            zebraCommand.sendSuccessMsg();
            return;
        }

        if (BasisCommandCode.TMSOFFON.cmd() == zebraCommand.getCmd()){
            TmsServerInfo serverInfo = TmsConfigInfoManager.getInstance().getServerInfo();
            EmptyMessage emptyMessage = (EmptyMessage) zebraCommand.getRequest();
            serverInfo.setOnline(emptyMessage.getMsg());
            log.warn("TMSOFFON {} {}", serverInfo.toString(), zebraCommand.toString());
            return;
        }

        if (BasisCommandCode.TMSTORA.cmd() == zebraCommand.getCmd()){
            TmsServerInfo serverInfo = TmsConfigInfoManager.getInstance().getServerInfo();
            EmptyMessage emptyMessage = (EmptyMessage) zebraCommand.getRequest();
            serverInfo.setOnline(emptyMessage.getMsg());
            log.warn("TMSOFFON {} {} `", serverInfo.toString(),  TmsConfigInfoManager.getInstance().buildGatewayLinkTms());
            return;
        }

        if (log.isInfoEnabled()){
            log.info("Request {}", zebraCommand.toString());
        }

        //--------执行---cmd---handler--------
        if (PoolType.DISRUPTOR == zebraCommand.getPoolType()){
            Executor executor =  TmsExecutorManager.getInstance().getDisruptorByLong(zebraCommand.getUserId());
            executor = null == executor ? TmsExecutorManager.getInstance().getDefaultExecutor() : executor;
            executor.execute(() ->  doHandlerRead(zebraCommand));
            return;
        }

        TmsExecutorManager.getInstance().getDefaultExecutor().execute(() ->  doHandlerRead(zebraCommand));
    }

    private void doHandlerRead(ZebraCommand zebraCommand){
        try {
            doHandler(zebraCommand);
        }catch (ZebraException e){
            log.error("Handler process zebraException {} {} {}", e.getMessage(), zebraCommand.toString());
            zebraCommand.sendFailureCode(e.getExceptionCode());
        }catch (Exception e) {
            log.error(String.format("Handler process exception CMD: %d %s", zebraCommand.getCmd(), zebraCommand.toString()), e);
            zebraCommand.sendFailureCode( StateCode.SysException.code());
        }
    }

    public abstract void doHandler(ZebraCommand command)throws Exception;


    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Connection connection = Connection.getByChannel(ctx.channel());
        if (null == connection){
            log.error("ChannelInactive connection Illegal {}", ctx.channel().toString());
            return;
        }

        log.warn("Tms Handler Inactive! remove connection {} ", connection.toString());
        if (ServerType.Register.value() == connection.getSeverType().value()){
            TmsConfigInfoManager.getInstance().removeRegister(connection);
            log.warn("Tms Register Info {} ", StrUtil.join(", ", TmsConfigInfoManager.getInstance().findRegisterALL()));
        }else {
            TmsConfigInfoManager.getInstance().removeGwConnection(connection);
            TmsSendMessageUtil.sendLinksToRA();
            doChannelInactive(connection);
        }
    }

    public abstract void doChannelInactive(Connection ctx)throws Exception;


}
